package com.dede.tablayouttest;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;

/**
 * @author hsh
 * @date 2017/12/20 9:33.
 * @doc
 */
public class ColorView extends FrameLayout {

    private static final String TAG = "ColorView";

    ImageView mIvAnim;

    Animator mAnimator;
    // RippleDrawable
    Drawable mPressDrawable;
    Drawable mDrawable;
    long mDuration = 500;

    private Rect rect = new Rect();

    public ColorView(@NonNull Context context) {
        this(context, null);
    }

    public ColorView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ColorView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public ColorView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        // android:background="?attr/selectableItemBackgroundBorderless"
        final int[] attrs = new int[]{android.R.attr.selectableItemBackgroundBorderless};
        final TypedArray ta = getContext().obtainStyledAttributes(attrs);
        // RippleDrawable
        mPressDrawable = ta.getDrawable(0);
        ta.recycle();

        mIvAnim = new ImageView(getContext());
        ViewCompat.setBackground(mIvAnim, this.mPressDrawable);// 先设置背景，否则第一次水波纹会出现中间
        mIvAnim.setClickable(true);
        addView(mIvAnim, new FrameLayout.LayoutParams(-1, -1));
    }

    @Override
    public void setBackground(Drawable background) {
        mDrawable = background;
        super.setBackground(background);
    }

    public void animDuration(long duration) {
        this.mDuration = duration;
    }

    public void startAnim(int color) {
        startAnim(color, getWidth() / 2, getHeight() / 2);
    }

    public void startAnim(int color, int centerX, int centerY) {
        if (mDrawable instanceof ColorDrawable) {
            ColorDrawable colorDrawable = (ColorDrawable) this.mDrawable;
            int mColor = colorDrawable.getColor();
            if (mColor == color) {
                onPressAnim(centerX, centerY);
                return;
            }
        }
        ColorDrawable drawable = new ColorDrawable(color);
        startAnim(drawable, centerX, centerY);
    }

    public void startAnim(Drawable drawable) {
        startAnim(drawable, getWidth() / 2, getHeight() / 2);
    }

    public void startAnim(Drawable drawable, int centerX, int centerY) {
        if (drawable == mDrawable) {
            onPressAnim(centerX, centerY);
            return;
        }
        mDrawable = drawable;
        playAnim(centerX, centerY);
    }

    public void startAnimWithView(int color, View view) {
        if (view == null) {
            Log.w(TAG, "startAnimWithView: view == null");
            startAnim(color);
        } else {
            boolean visibleRect = view.getGlobalVisibleRect(rect);
            if (visibleRect) {
                startAnim(color, rect.left + rect.width() / 2, rect.top + rect.height() / 2);
            } else {
                Log.i(TAG, "startAnimWithView: " + view + ". width <= 0 || height <= 0");
            }
        }
    }

    public void startAnimWithView(Drawable drawable, View view) {
        if (view == null) {
            Log.w(TAG, "startAnimWithView: view == null");
            startAnim(drawable);
        } else {
            boolean visibleRect = view.getGlobalVisibleRect(rect);
            if (visibleRect) {
                startAnim(drawable, rect.left + rect.width() / 2, rect.top + rect.height() / 2);
            } else {
                Log.i(TAG, "startAnimWithView: " + view + ". width <= 0 || height <= 0");
            }
        }
    }

    protected void playAnim(int centerX, int centerY) {
        if (mAnimator != null && mAnimator.isRunning()) {
            mAnimator.removeAllListeners();
            mAnimator.cancel();
        }

        mAnimator = createAnim(centerX, centerY);
        mAnimator.start();
    }

    /**
     * 按下水波纹动画
     *
     * @param x
     * @param y
     */
    protected void onPressAnim(float x, float y) {
        ViewCompat.setBackground(mIvAnim, mPressDrawable);
        mPressDrawable.setHotspot(x, y);
        mIvAnim.setPressed(true);
        mIvAnim.setPressed(false);
    }

    LinearInterpolator interpolator = new LinearInterpolator();

    protected Animator createAnim(int centerX, int centerY) {
        float radiusWidth = getDistance(getWidth(), centerX);
        float radiusHeight = getDistance(getHeight(), centerY);
        double endRadius = Math.sqrt(Math.pow(radiusHeight, 2) + Math.pow(radiusWidth, 2));// 勾股定理拿到斜边长

        Animator animator = ViewAnimationUtils.createCircularReveal(mIvAnim, centerX, centerY, 0, (float) endRadius);
        animator.setDuration(mDuration);
        animator.setInterpolator(interpolator);
        animator.addListener(new AnimListener(mIvAnim, this, mDrawable, mPressDrawable));
        return animator;
    }

    private float getDistance(float max, float i) {
        if (max / 2 > i) {
            return max - i;
        } else {
            return i;
        }
    }

    static class AnimListener extends AnimatorListenerAdapter {

        private final ImageView mAnim;
        private final Drawable mDrawable;
        private final View mView;
        private final Drawable mPressDrawable;

        AnimListener(ImageView anim, View view, Drawable drawable, Drawable pressDrawable) {
            this.mAnim = anim;
            this.mView = view;
            this.mDrawable = drawable;
            this.mPressDrawable = pressDrawable;
        }

        @Override
        public void onAnimationStart(Animator animation) {
            mAnim.setBackground(mDrawable);
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            mView.setBackground(mDrawable);
            mAnim.setBackground(mPressDrawable);
        }
    }

}
